package com.chif.gulimall.search.thread;

import java.util.concurrent.*;

/**
 * @author liuzilong
 * @date 2023/3/1 15:21
 */
public class ThreadTest {


    public static ExecutorService execute = Executors.newFixedThreadPool(10);


    public static void main(String[] args) throws ExecutionException, InterruptedException {

        /**
         * 方法完成后的感知
         */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, execute).whenComplete((res,excption)->{
//            System.out.println("异步任务成功完成了..结果是"+res+"异常是："+excption);
//        }).exceptionally(throwable -> {
//            //可以感知异常，同时修改返回结果(处理)
//            return 10;
//        });


        /**
         * 方法完成后的处理
         */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, execute).handle((res,thr)->{
//            if (res!=null){
//                return res*2;
//            }
//            if (thr!=null){
//                return 0;
//            }
//            return 0;
//        });


        /**
         * 多线程编排
         * thenRunXXX:不能获取到上一个线程的返回结果
         * thenAcceptXXX:能接收上一步返回结果，无返回值
         * thenApplyXXX:能接收上一步返回结果，有返回值
         */
//        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 4;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, execute).thenApplyAsync((res) -> {
//            System.out.println("任务2启动了" + res);
//            return "Hello" + res;
//        }, execute);
//
//        System.out.println(future.get());


        /**
         * 两个线程都完成
         */
//        CompletableFuture<Object> future1 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务1线程：" + Thread.currentThread().getId());
//            int i = 10 / 4;
//            System.out.println("任务1结束：" + i);
//            return i;
//        }, execute);
//
//        CompletableFuture<Object> future2 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务2开始");
//            System.out.println("任务2结束");
//            return "hello";
//        }, execute);


//        future1.runAfterBothAsync(future2,()->{
//            System.out.println("任务3开始");
//            System.out.println("任务3结束");
//        },execute);

        //接收f1和f2的返回值
//        future1.thenAcceptBothAsync(future2,(f1,f2)->{
//            System.out.println("任务3开始之前的结果"+f1+f2);
//            System.out.println("任务3结束");
//        },execute);


        //接收并处理返回f1和f2的返回值
//        CompletableFuture<String> future = future1.thenCombineAsync(future2, (f1, f2) -> {
//            System.out.println("任务3开始之前的结果" + f1 + f2);
//            System.out.println("任务3结束");
//            return f1 + ":" + f2;
//        }, execute);
//
//        System.out.println(future.get());



        //两个任务只要有一个任务完成，就执行任务3
//        future1.runAfterEitherAsync(future2,()->{
//            System.out.println("任务3执行");
//        },execute);

//        future1.acceptEitherAsync(future2,(res)->{
//            System.out.println("任务3执行,之前的结果为"+res);
//        },execute);

//        CompletableFuture<String> future = future1.applyToEitherAsync(future2, (res) -> {
//            System.out.println("任务3执行,之前的结果为" + res);
//            return "hello 任务3";
//        }, execute);
//
//        System.out.println(future.get());


//        CompletableFuture.runAsync(()->{
//            System.out.println("当前线程："+Thread.currentThread().getId());
//            int i= 10/2;
//            System.out.println("运行结果："+i);
//        },execute);



        //商城查询商品详情业务模拟
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商城的图片信息");
            return "hello.jpg";
        });

        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商城的属性信息");
            return "黑色+256G";
        });


        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商城的介绍");
            return "华为";
        });

        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futureDesc);
        allOf.get();//等待所有结果完成
        System.out.println(anyOf.get());//等待任一结果完成


    }

    /**
     * 创建线程的4种方式
     * 1、继承Thread
     * 2、实现RunnabLe接口
     * 3、实现CaLLable接口 + FutureTask (可以拿到返回结果，可以处理异常)
     * 4、线程池 应该将所有的线程任务交给线程池执行
     * 1 2 不能得到返回值 3 可以获取返回值
     * 1 2 3 都不能控制资源 4 可以控制资源，性能稳定
     * @param args
     */
    public static void thread(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main start");
//        Runable01 thread01 = new Runable01();
//        new Thread(thread01).start();

//        FutureTask<Integer> integerFutureTask = new FutureTask<>(new CaLLable01());
//        new Thread(integerFutureTask).start();
        //FutureTask阻塞等待整个线程执行完成，获取返回结果
//        Integer integer = integerFutureTask.get();


        /**
         * 线程池
         * 1. 创建
         *      Executors
         *      ThreadPoolExecutor
         * 2.ThreadPoolExecutor七大参数
         *  corePoolSize[5] 核心线程数(一直存在，除非allowCoreThreadTimeOut)；线程池创建好以后就准备就绪的线程数量，就等待来接收异步任务去执行
         *  maximumPoolSize[200] 最大线程数量；控制资源并发
         *  keepAliveTime 存活时间，如果当前正在运行的线程的数量大于corePoolSize，释放空闲的线程(maximumPoolSize-corePoolSize)，只要线程空闲>keepAliveTime
         *  unit 时间单位
         *  BlockingQueue<Runnable> workQueue 阻塞队列，如果任务有很多，会将多的任务放在队列中，只要有空闲线程，就会去队列中执行新的任务
         *  ThreadFactory threadFactory 线程的创建工厂
         *  RejectedExecutionHandler handler 如果阻塞队列满了，按照指定的拒绝策略拒绝执行任务 CallerRunsPolicy 同步执行剩余任务 AbortPolicy 丢弃剩余执行任务
         *
         */

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
                200,10,TimeUnit.SECONDS,new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
        //当前系统中池只有一两个，每个异步任务提交给线程池让他自己去执行
        //Executors.newCachedThreadPool(); //没有核心线程线程池
        //Executors.newFixedThreadPool();  //固定线程数量线程池
        //Executors.newScheduledThreadPool();//定时任务线程池
        //Executors.newSingleThreadExecutor();//单线程线程池
        execute.execute(new Runable01());

        System.out.println("main stop");

    }


    public static class Thread01 extends Thread{
        @Override
        public void run() {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i= 10/2;
            System.out.println("运行结果："+i);
        }
    }

    public static class Runable01 implements Runnable{
        @Override
        public void run() {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i= 10/2;
            System.out.println("运行结果："+i);
        }
    }

    public static class CaLLable01 implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i= 10/2;
            System.out.println("运行结果："+i);
            return i;
        }
    }
}
